%{
#include <iostream>
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>

#define YYSTYPE atributos

using namespace std;

int n_label=0;

int yylex(void);
void yyerror(string);
string gerarLabel(string comentario);
string geraTemp(string tipo);
string inttostring(int num ); 


struct atributos
{
	string valor,codigo,temp;
};

struct n_temp
{
	int inteiro,real,logico,texto,caractere;
};






struct lista {
	int info;
	struct lista* prox;
};

typedef struct lista Lista;
Lista* l;

/* função de inicialização: retorna uma lista vazia */
Lista* inicializa (void)
{
	return NULL;
}

/* inserção no início: retorna a lista atualizada */
Lista* insere (Lista* l, int i)
{
	Lista* novo = (Lista*) malloc(sizeof(Lista));
	novo->info = i;
	novo->prox = l;
	return novo;
}

/* função imprime: imprime valores dos elementos */
void imprime (Lista* l)
{
	Lista* p;
	/* variável auxiliar para percorrer a lista */
	for (p = l; p != NULL; p = p->prox)
	printf("info = %d\n", p->info);
}

/* função busca: busca um elemento na lista */
Lista* busca (Lista* l, int v)
{
	Lista* p;
	for (p=l; p!=NULL; p=p->prox)
	    if (p->info == v)
		return p;
	return NULL;
	/* não achou o elemento */
}




%}

%token TK_TIPO TK_MAIN 
%token TK_FCH TK_ACH TK_APAR TK_FPAR TK_PV TK_VI TK_ID TK_RECEBE TK_INCLUDE
%token TK_FOR TK_IF TK_ELSE TK_WHILE TK_DO TK_SWITCH TK_CASE TK_RETURN 
%token TK_IGUAL TK_E TK_OU TK_MAI TK_MEI TK_MA TK_ME TK_DIF TK_MAIS TK_MENOS TK_DIV TK_MULT
%token TK_FIM TK_ERROR NUM_INT NUM_FLT TK_PALAVRA TK_ESCREVA

%start INICIO


%%

INICIO		: BIBLIOTECA 
 		;
 		
BIBLIOTECA	: TK_INCLUDE BIBLIOTECA 
		| GLOBAL 
		;
		
PRINCIPAL	: TK_TIPO TK_MAIN TK_APAR SEG_DECLARA TK_FPAR BLOCO GLOBAL 
		;
	
GLOBAL		: TK_TIPO TK_ID TK_APAR SEG_DECLARA TK_FPAR BLOCO GLOBAL 
		| TK_TIPO TK_ID TK_APAR SEG_DECLARA TK_FPAR TK_PV GLOBAL 
		| DECLARACAO TK_PV GLOBAL 
		| PRINCIPAL
		| /*vazio*/
		;

BLOCO		: COMANDO 
		| TK_ACH COMANDOS TK_FCH 
		;

COMANDOS	: COMANDOS COMANDO 
		| COMANDO 
		;
		
COMANDO		: COM_FOR 
           	| COM_IF 
          	| COM_WHILE 
         	| COM_SWITCH 
          	| CH_FUNCAO 
      		| FINAL_LINHA 
		;
			
EXP		: EXP TK_MAIS EXP 
		| EXP TK_MENOS EXP 
		| EXP TK_DIV EXP 
		| EXP TK_MULT EXP 
 		| TK_APAR EXP TK_FPAR 
		| NUM_INT
		| NUM_FLT
		| TK_ID
		| TK_APAR VARIAVEL TK_FPAR 
		| EXP OPERACAO EXP  
		| TK_MAIS  
		| TK_MENOS
		| TK_PALAVRA
		| TK_ESCREVA
		;

DECLARACAO	: 
		TK_TIPO VARIAVEL 
		| VARIAVEL 
       		;

VARIAVEL	: TK_ID
		| TK_ID TK_RECEBE EXP  
		/*{
			l = insere(l,(int)$2.numero);
			printf("%d",l->info);
		}*/
		| TK_ID TK_RECEBE VARIAVEL			
		| TK_ID TK_MAIS EXP
		| TK_ID TK_MENOS EXP
		;	

SEG_DECLARA	: /*Vazio*/
		| TK_TIPO TK_ID			
		| TK_TIPO TK_ID TK_VI SEG_DECLARA 
    		;					

FINAL_LINHA	: EXP TK_PV
           	| DECLARACAO TK_PV 
           	| EXP TK_VI 
           	| DECLARACAO TK_VI
		;			
					
COM_FOR		: TK_FOR TK_APAR VARIAVEL TK_PV VARIAVEL OPERACAO EXP TK_PV VARIAVEL TK_FPAR BLOCO
		| TK_FOR TK_APAR TK_PV TK_PV TK_FPAR BLOCO
		;

COM_IF		: TK_IF TK_APAR EXP OPERACAO EXP TK_FPAR BLOCO
		| TK_IF TK_APAR EXP OPERACAO EXP TK_FPAR BLOCO TK_ELSE BLOCO
		;

COM_WHILE	: TK_WHILE TK_APAR EXP OPERACAO EXP TK_FPAR BLOCO
		| TK_DO BLOCO TK_WHILE TK_APAR EXP OPERACAO EXP TK_FPAR TK_PV
		;

COM_SWITCH	:
		;

CH_FUNCAO	: TK_TIPO TK_ID TK_APAR SEG_DECLARA TK_FPAR BLOCO
		| 
		;

OPERACAO	: TK_IGUAL
		| TK_E
		| TK_OU
		| TK_MAI
		| TK_MEI
		| TK_MA
		| TK_ME
		| TK_DIF
		;						
	

				
			
%%


#include "lex.yy.c"

int yyparse();

int main( int argc, char* argv[] )
{
	yyparse();

	return 0;
}

void yyerror( string MSG )
{
	cout << MSG << endl;
	exit (0);
}	

string gerarLabel(string comentario) {
	return comentario + inttostring(++n_label);
}

string inttostring( int num ) {
	stringstream temp;
	temp << num;
	return temp.str(); 
}
/*
string geraTemp(string tipo)
{
	if(tipo=="inteiro")
		return "T_"+tipo+inttostring(n_temp.inteiro++);
	else if(tipo=="real")
		return "T_"+tipo+inttostring(n_temp.real++);
	else if(tipo=="logico")
		return "T_"+tipo+inttostring(n_temp.logico++);
	else if(tipo=="texto")
		return "T_"+tipo+inttostring(n_temp.texto++);
	else if(tipo=="caractere")
		return "T_"+tipo+inttostring(n_temp.caractere++);	
	else
		erro("tipo invalido"+tipo);
}
*/

		
